<template>
  <q-tr ref="TableTH" :class="headerCls" :props="props" @click.stop="handleClickRow('row')">
    <q-th v-if="selection && isShow" key="selection" class="qx-table--selection" rowspan="100%" @click.stop="">
      <slot v-if="selection === 'multiple'" :props="props" name="selection"></slot>
    </q-th>
    <q-th v-if="isShow" key="index" :class="headerCellCls({})" :props="props" :style="{ left }" class="qx-table--index"
          rowspan="100%" @click.stop="handleClickRow('cell', {})">
      #
    </q-th>
    <template v-for="(column, index) in leftCols" :key="column.name">
      <q-th :class="headerCellCls(column)" :colSpan="column.colSpan" :props="formatProps(column)"
            :rowSpan="column.rowSpan" :style="fixedLeft(column, index)" @click.stop="handleClickRow('cell', column)">
        <template v-if="column.headerSlot">
          <slot :name="column.field + 'H'" :row="column"></slot>
        </template>
        <template v-else>{{ column.label }}</template>
      </q-th>
    </template>
    <template v-for="column in mainCols" :key="column.name">
      <q-th :class="headerCellCls(column)" :colSpan="column.colSpan" :props="formatProps(column)"
            :rowSpan="column.rowSpan" @click.stop="handleClickRow('cell', column)">
        <template v-if="column.headerSlot">
          <slot :name="column.field + 'H'" :row="column"></slot>
        </template>
        <template v-else>{{ column.label }}</template>
      </q-th>
    </template>
    <template v-for="(column, index) in rightCols" :key="column.name">
      <q-th :class="headerCellCls(column)" :colSpan="column.colSpan" :props="formatProps(column)"
            :rowSpan="column.rowSpan" :style="fixedRight(column, index)" @click.stop="handleClickRow('cell', column)">
        <template v-if="column.headerSlot">
          <slot :name="column.field + 'H'" :row="column"></slot>
        </template>
        <template v-else>{{ column.label }}</template>
      </q-th>
    </template>
    <q-th v-if="isShow" key="menu" :class="headerCellCls({})" :props="props" class="qx-table--menu" rowspan="100%">
      {{ menu.label }}
    </q-th>
  </q-tr>
</template>

<script setup>
import { getResult } from 'components/tableUtils'
import { dom } from 'quasar'
import { isEmpty } from 'src/utils/utils'
import { computed, ref, watchEffect } from 'vue'

const prefix = 'qx-fixed-column-'

const prop = defineProps({
  index: Number, props: Object, columns: Array, selection: String, headerClick: Function, headerCellClick: Function
})
const fixedInfo = defineModel('fixedColsInfo', { type: Object, default: () => ({}) })

const leftCols = ref([])
const mainCols = ref([])
const rightCols = ref([])
const TableTH = ref(null)
const isShow = computed(() => !prop.index)
const left = computed(() => prop.selection ? '2.25rem' : 0)
const menu = computed(() => (prop.columns || []).find(el => el.name === 'menu') || {})
const formatProps = computed(() => column => isEmpty(column.children) ? prop.props : '')
const fixedLeft = computed(() => (column = {}, index = 0) => {
  if (!TableTH.value) return
  const node = TableTH.value.$el.querySelector(`.${prefix}${column.name}`)
  if (!node) return
  const leftWidth =
    !index ? dom.offset(node).left - indexNodeLeft() : fixedInfo.value[leftCols.value[index - 1].name] + dom.width(node)
  fixedInfo.value[column.name] = leftWidth
  return { left: `${leftWidth}px` }
})
const fixedRight = computed(() => (column = {}, index = 0) => {
  if (!TableTH.value) return
  let rightWidth
  if (index === 0) rightWidth = menuNodeWidth()
  else {
    const node = TableTH.value.$el.querySelector(`.${prefix}${leftCols.value[index - 1].name}`)
    if (!node) rightWidth = fixedInfo.value[column.name]
    else rightWidth = fixedInfo.value[column.name] + dom.width(node)
  }
  fixedInfo.value[column.name] = rightWidth
  return { right: `${rightWidth}px` }
})
const headerCls = computed(() => {
  const cls = isShow.value ? '' : 'non-first-row', { headerCellClick, headerClick } = prop
  return headerClick || headerCellClick ? cls + 'cursor-pointer cursor-hover' : cls
})
const headerCellCls = computed(() => {
  return (column = {}) => {
    let cls = 'text-body1 text-capitalize '
    if (column.fixed) cls += `${prefix}${column.name} `
    if (column.headerClasses) cls += getResult(column.headerClasses, prop.props)
    return column.headerClick ? cls + 'cursor-pointer text-primary cursor-hover' : cls
  }
})

const splitCols = () => {
  leftCols.value = []
  mainCols.value = []
  rightCols.value = []
  for (const col of prop.columns || []) {
    if (['index', 'menu'].includes(col.name) || !col.rowSpan || !col.colSpan) continue
    if (!col.fixed) mainCols.value.push(col)
    else if (col.fixed === 'left') leftCols.value.push(col)
    else if (col.fixed === 'right') rightCols.value.push(col)
  }
}
watchEffect(splitCols)

const indexNodeLeft = () => {
  if (!TableTH.value) return 0
  const node = TableTH.value.$el.querySelector('.qx-table--index')
  if (!node) return 0
  return ((dom.offset(node) || {}).left || 0) - parseInt(dom.style(node, 'left'))
}
const menuNodeWidth = () => {
  if (!TableTH.value) return 0
  const node = TableTH.value.$el.querySelector('.qx-table--menu')
  if (!node) return 0
  return dom.width(node)
}
const handleClickRow = (action, column = {}) => {
  const { headerClick, headerCellClick, props = {} } = prop, { colsMap, row, rowIndex = 0 } = props
  if (action === 'row') return headerClick && headerClick(row, column, colsMap, rowIndex)
  if (action !== 'cell') return
  if (column.headerClick) return column.headerClick(row, column, rowIndex)
  if (headerCellClick) return headerCellClick(row, column, colsMap, rowIndex)
  headerClick && headerClick(row, column, colsMap, rowIndex)
}
</script>